home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i099: Sun RPC Source (rpc2), Part11/11
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: cca!SUN.COM!marks (Mark Stein)
- Mod.sources: Volume 6, Issue 99
- Archive-name: rpc2/Part11
-
- [ I have only verified that this unpacks correctly. --r$ ]
-
- Sun RPC source (part 11 of 11). This software package contains code
- and documentation for Revision 3.0 of the Sun Remote Procedure Call
- library. In addition, a beta version of the XDR/RPC protocol compiler
- is included. Comments about this latest release may be mailed to
- sun!rpc or rpc@sun.com.
-
- Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- unrestricted use provided that this legend is included on all tape
- media and as a part of the software program in whole or part. Users
- may copy or modify Sun RPC without charge, but are not authorized to
- license or distribute it to anyone else except as part of a product or
- program developed by the user.
-
- - - - - - - - - - C U T - H E R E - - - - - - - - - - - - - - - - - -
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create:
- # rpc/rpcgen/rpc_util.c
- # rpc/rpcgen/rpc_util.h
- # rpc/rpcgen/rpcgen.1
- # rpc/rpcgen/xdr_update.c
- # rpc/rpcgen/test/Makefile
- # rpc/rpcgen/test/demo_clnt.c
- # rpc/rpcgen/test/demo_proc.c
- # rpc/rpcgen/test/demo_xdr.x
- # This archive created: Mon Jul 14 16:55:53 1986
- export PATH; PATH=/bin:/usr/bin:$PATH
- for d in rpc rpc/doc rpc/rpclib rpc/tools rpc/toys rpc/rpclib/profiled rpc/rpcgen rpc/rpcgen/test
- do
- if test ! -d $d
- then
- echo "shar: Making directory $d"
- mkdir $d
- chmod 755 $d
- fi
- done
- echo shar: "extracting 'rpc/rpcgen/rpc_util.c'" '(4145 characters)'
- if test -f 'rpc/rpcgen/rpc_util.c'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/rpc_util.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpc_util.c'
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)rpc_util.c 1.1 86/03/26 (C) 1986 SMI";
- X#endif
- X
- X/*
- X * rpc_util.c, Utility routines for the RPC protocol compiler
- X * Copyright (C) 1986, Sun Microsystems, Inc.
- X */
- X#include <stdio.h>
- X#include "rpc_scan.h"
- X#include "rpc_util.h"
- X
- Xchar curline[MAXLINESIZE]; /* current read line */
- Xchar *where = curline; /* current point in line */
- Xint linenum = 0; /* current line number */
- X
- Xchar *infile; /* input filename */
- Xchar *outfile; /* output filename */
- Xchar *outfile2; /* possible other output filename */
- X
- XFILE *fout; /* file pointer of current output */
- XFILE *fin; /* file pointer of current input */
- X
- Xlist *printed; /* list of printed routines */
- Xlist *defined; /* list of defined things */
- X
- X/*
- X * Reinitialize the world
- X */
- Xreinitialize()
- X{
- X bzero(curline,MAXLINESIZE);
- X where = curline;
- X linenum = 0;
- X printed = NULL;
- X defined = NULL;
- X}
- X
- X/*
- X * string equality
- X */
- Xstreq(a,b)
- X char *a;
- X char *b;
- X{
- X return(strcmp(a,b) == 0);
- X}
- X
- X/*
- X * find a value in a list
- X */
- Xchar *
- Xfindval(lst,val,cmp)
- X list *lst;
- X char *val;
- X int (*cmp)();
- X{
- X for (; lst != NULL; lst = lst->next) {
- X if ((*cmp)(lst->val,val)) {
- X return(lst->val);
- X }
- X }
- X return(NULL);
- X}
- X
- X/*
- X * store a value in a list
- X */
- Xvoid
- Xstoreval(lstp,val)
- X list **lstp;
- X char *val;
- X{
- X list **l;
- X list *lst;
- X
- X for (l = lstp; *l != NULL; l = (list **) &(*l)->next)
- X ;
- X lst = ALLOC(list);
- X lst->val = val;
- X lst->next = NULL;
- X *l = lst;
- X}
- X
- X
- X/*
- X * print a useful (?) error message, and then die
- X */
- Xvoid
- Xerror(msg)
- X char *msg;
- X{
- X extern char *outfile;
- X
- X printwhere();
- X fprintf(stderr,"%s, line %d: ",infile ? infile : "<stdin>", linenum);
- X fprintf(stderr,"%s\n",msg);
- X crash();
- X}
- X
- X/*
- X * Something went wrong, unlink any files
- X * that we may have created and then die.
- X */
- Xcrash()
- X{
- X if (outfile) {
- X unlink(outfile);
- X }
- X if (outfile2) {
- X unlink(outfile2);
- X }
- X exit(1);
- X}
- X
- X
- X
- Xstatic char expectbuf[100];
- Xstatic char *toktostr();
- X
- X/*
- X * error, token encountered was not the expected one
- X */
- Xvoid
- Xexpected1(exp1)
- X tok_kind exp1;
- X{
- X sprintf(expectbuf,"expected '%s'",
- X toktostr(exp1));
- X error(expectbuf);
- X}
- X
- X/*
- X * error, token encountered was not one of two expected ones
- X */
- Xvoid
- Xexpected2(exp1,exp2)
- X tok_kind exp1,exp2;
- X{
- X sprintf(expectbuf,"expected '%s' or '%s'",
- X toktostr(exp1),
- X toktostr(exp2));
- X error(expectbuf);
- X}
- X
- X/*
- X * error, token encountered was not one of 3 expected ones
- X */
- Xvoid
- Xexpected3(exp1,exp2,exp3)
- X tok_kind exp1,exp2,exp3;
- X{
- X sprintf(expectbuf,"expected '%s', '%s' or '%s'",
- X toktostr(exp1),
- X toktostr(exp2),
- X toktostr(exp3));
- X error(expectbuf);
- X}
- X
- X
- X
- Xstatic token tokstrings[] = {
- X { TOK_IDENT, "identifier" },
- X { TOK_CONST, "constant" },
- X { TOK_RPAREN, ")" },
- X { TOK_LPAREN, "(" },
- X { TOK_RBRACE, "}" },
- X { TOK_LBRACE, "{" },
- X { TOK_LBRACKET, "[" },
- X { TOK_RBRACKET, "]" },
- X { TOK_STAR, "*" },
- X { TOK_COMMA, "," },
- X { TOK_EQUAL, "=" },
- X { TOK_COLON, ":" },
- X { TOK_SEMICOLON, ";" },
- X { TOK_UNION, "union" },
- X { TOK_STRUCT, "struct" },
- X { TOK_SWITCH, "switch" },
- X { TOK_CASE, "case" },
- X { TOK_DEFAULT, "default" },
- X { TOK_ENUM, "enum" },
- X { TOK_ARRAY, "array" },
- X { TOK_TYPEDEF, "typedef" },
- X { TOK_INT, "int" },
- X { TOK_SHORT, "short" },
- X { TOK_LONG, "long" },
- X { TOK_UNSIGNED, "unsigned" },
- X { TOK_DOUBLE, "double" },
- X { TOK_FLOAT, "float" },
- X { TOK_CHAR, "char" },
- X { TOK_STRING, "string" },
- X { TOK_OPAQUE, "opaque" },
- X { TOK_BOOL, "bool" },
- X { TOK_VOID, "void" },
- X { TOK_PROGRAM, "program" },
- X { TOK_VERSION, "version" },
- X { TOK_EOF, "??????" }
- X};
- X
- Xstatic char *
- Xtoktostr(kind)
- X tok_kind kind;
- X{
- X token *sp;
- X
- X for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++)
- X ;
- X return(sp->str);
- X}
- X
- X
- Xstatic
- Xprintbuf()
- X{
- X char c;
- X int i;
- X int cnt;
- X
- X# define TABSIZE 4
- X
- X for (i = 0; c = curline[i]; i++) {
- X if (c == '\t') {
- X cnt = 8 - (i % TABSIZE);
- X c = ' ';
- X } else {
- X cnt = 1;
- X }
- X while (cnt--) {
- X putc(c,stderr);
- X }
- X }
- X}
- X
- X
- Xstatic
- Xprintwhere()
- X{
- X int i;
- X char c;
- X int cnt;
- X
- X printbuf();
- X for (i = 0; i < where - curline; i++) {
- X c = curline[i];
- X if (c == '\t') {
- X cnt = 8 - (i % TABSIZE);
- X } else {
- X cnt = 1;
- X }
- X while (cnt--) {
- X putc('^',stderr);
- X }
- X }
- X putc('\n',stderr);
- X}
- SHAR_EOF
- if test 4145 -ne "`wc -c < 'rpc/rpcgen/rpc_util.c'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/rpc_util.c'" '(should have been 4145 characters)'
- fi
- chmod 444 'rpc/rpcgen/rpc_util.c'
- fi
- echo shar: "extracting 'rpc/rpcgen/rpc_util.h'" '(1202 characters)'
- if test -f 'rpc/rpcgen/rpc_util.h'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/rpc_util.h'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpc_util.h'
- X/* @(#)rpc_util.h 1.1 86/03/26 (C) 1986 SMI */
- X
- X/*
- X * rpc_util.h, Useful definitions for the RPC protocol compiler
- X * Copyright (C) 1986, Sun Microsystems, Inc.
- X */
- X
- Xextern char *malloc();
- Xextern char *sprintf();
- X#define alloc(size) malloc((unsigned)(size))
- X#define ALLOC(object) (object *) malloc(sizeof(object))
- X
- X#define OFF 0
- X#define ON 1
- X
- Xstruct list {
- X char *val;
- X struct list *next;
- X};
- Xtypedef struct list list;
- X
- X/*
- X * Global variables
- X */
- X#define MAXLINESIZE 1024
- Xextern char curline[MAXLINESIZE];
- Xextern char *where;
- Xextern int linenum;
- X
- Xextern char *outfile;
- Xextern char *outfile2;
- Xextern char *infile;
- Xextern FILE *fout;
- Xextern FILE *fin;
- X
- Xextern list *printed;
- Xextern list *defined;
- X
- X
- X/*
- X * rpc_util routines
- X */
- Xvoid storeval();
- X#define STOREVAL(list,item) \
- X storeval(list,(char *)item)
- X
- Xchar *findval();
- X#define FINDVAL(list,item,finder) \
- X findval(list, (char *) item, finder)
- X
- Xint streq();
- Xvoid error();
- Xvoid expected1();
- Xvoid expected2();
- Xvoid expected3();
- X
- X/*
- X * rpc_cout routines
- X */
- Xvoid cprint();
- Xvoid emit();
- X
- X/*
- X * rpc_hout routines
- X */
- Xvoid print_datadef();
- Xvoid print_funcdefs();
- X
- X/*
- X * rpc_svcout routines
- X */
- Xvoid write_most();
- Xvoid write_register();
- Xvoid write_rest();
- X
- SHAR_EOF
- if test 1202 -ne "`wc -c < 'rpc/rpcgen/rpc_util.h'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/rpc_util.h'" '(should have been 1202 characters)'
- fi
- chmod 444 'rpc/rpcgen/rpc_util.h'
- fi
- echo shar: "extracting 'rpc/rpcgen/rpcgen.1'" '(11239 characters)'
- if test -f 'rpc/rpcgen/rpcgen.1'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/rpcgen.1'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/rpcgen.1'
- X.\" @(#)rpcgen.1 1.1 86/04/15 SMI
- X.TH RPCGEN 1 "11 March 1986"
- X.SH NAME
- Xrpcgen \- an RPC protocol compiler
- X.SH SYNOPSIS
- X\fBrpcgen\fP \fB-h\fP \fB[-o \fIoutfile\fP]\fP \fB[\fIinputfile\fP]\fP
- X.br
- X\fBrpcgen\fP \fB-c\fP \fB[-o \fIoutfile\fP]\fP \fB[\fIinfile\fP]\fP
- X.br
- X\fBrpcgen\fP \fIinfile\fP
- X.br
- X\fBrpcgen\fP \fB[-s \fItransport\fP]*\fP \fB[-o\fP \fIoutfile\fP]\fP \fB[\fIinfile\fP]\fP
- X.br
- X.SH DESCRIPTION
- X\fIrpcgen\fP is a tool that generates
- X.B C
- Xcode to implement an
- X.SM RPC
- Xprotocol. The input to \fIrpcgen\fP is a language with striking
- Xsimilarity to
- X.B C
- Xknown as RPCL (Remote Procedure Call Language).
- X.I rpcgen
- Xoperates in four modes. The first mode is used to convert
- XRPCL definitions into
- X.B C
- Xdefinitions for use as a header file.
- XThe second mode compiles the XDR routines required to serialize the protocol
- Xdescribed by RPCL. The third mode compiles both, leaving the
- Xheader file in a file named \fIinfile\fP with a
- X.B .h
- Xextension and the XDR routines in \fIinfile\fP with a
- X.B .c
- Xextension. The fourth mode is used to compile an RPC server skeleton, so that
- Xall you have to do is write local procedures that know nothing about RPC
- Xin order to implement an RPC server.
- X.LP
- XThe input may contain
- X.BR C -style
- Xcomments and preprocessor directives. Comments are ignored, while the
- Xdirectives are simply stuffed uninterpreted in the output header file.
- X.LP
- XYou can customize some of your XDR routines by leaving those data
- Xtypes undefined. For every data type that is undefined, \fIrpcgen\fP
- Xwill assume that there exists a routine with the name `xdr_' prepended
- Xto the name of the undefined type.
- X.SH OPTIONS
- X.IP \fB-c\fP
- XCompile XDR routines.
- X.IP \fB-h\fP
- XCompile
- X.B C
- Xdata-definitions (a header file)
- X.IP "\fB-o\fP \fIoutfile\fP"
- XSpecify the name of the output file. If none is specified, standard
- Xoutput is used (\fB-c\fP, \fB-h\fP and \fB-s\fP modes only).
- X.IP "\fB-s\fP \fItransport\fP"
- XCompile a server, using the the given transport. The supported transports
- Xare \fBudp\fP and \fBtcp\fP. This option may be invoked more than once
- Xso as to compile a server that serves multiple transports.
- X.SH USAGE
- X.SS "RPCL Syntax Summary"
- XThis summary of RPCL syntax, which is used for
- X.I rpcgen
- Xinput, is intended more for aiding
- Xcomprehension than as an exact statement of the language.
- X.SS "Primitive Data Types"
- X.RS
- X.nf
- X[ \fBunsigned\fP ] \fBchar\fP
- X[ \fBunsigned\fP ] \fBshort\fP
- X[ \fBunsigned\fP ] \fBint\fP
- X[ \fBunsigned\fP ] \fBlong\fP
- X\fBunsigned\fP
- X\fBfloat\fP
- X\fBdouble\fP
- X\fBvoid\fP
- X\fBbool\fP
- X.fi
- X.RE
- XExcept for the added boolean data-type \fBbool\fP,
- XRPCL is identical to
- X.BR C .
- X\fIrpcgen\fP converts \fBbool\fP declarations to \fBint\fP declarations in the
- Xoutput header file (literally it is converted to a \fBbool_t\fP, which has been
- X\fB#define\fP'd to be an \fBint\fP). Also, \fBvoid\fP declarations
- Xmay appear only inside of
- X.B union
- Xand
- X.B program
- Xdefinitions. For those averse to typing the prefix
- X\fBunsigned\fP, the abbreviations \fBu_char\fP, \fBu_short\fP, \fBu_int\fP and
- X\fBu_long\fP are available.
- X.SS Declarations
- XRPCL allows only three kinds of declarations:
- X.LP
- X\fIdeclaration:\fP
- X.RS
- X.nf
- X\fIsimple-declaration\fP
- X\fIpointer-declaration\fP
- X\fIvector-declaration\fP
- X.fi
- X.RE
- X.LP
- X\fIsimple-declaration:\fP
- X.RS
- X\fItype-name\fP \fIobject-ident\fP
- X.RE
- X.LP
- X\fIpointer-declaration:\fP
- X.RS
- X\fItype-name\fP \fB*\fP\fIobject-ident\fP
- X.RE
- X.LP
- X\fIvector-declaration:\fP
- X.RS
- X\fItype-name\fP \fIobject-ident\fP\fB[\fP\fIsize\fP\fB]\fP
- X.RE
- X.LP
- X(\fIsize\fP can be either an integer or a symbolic constant)
- X.RE
- X.LP
- XRPCL declarations contain both limitations and extensions with
- Xrespect to
- X.BR C .
- XThe limitations are that you cannot declare
- Xmultidimensional arrays or pointers-to-pointers in-line (You
- Xcan still declare them though, using \fBtypedef\fP). There
- Xare two extensions:
- X.LP
- X.RS
- XOpaque data is declared as a vector as follows:
- X.LP
- X.RS
- X\fBopaque\fP \fIobject-ident\fP \fB[\fP \fIsize\fP \fB]\fP
- X.RE
- X.LP
- XIn the protocol, this results in an object of \fIsize\fP bytes. Note that
- Xthis is \fInot\fP the same as a declaration of \fIsize\fP characters,
- Xsince XDR characters are 32-bits. Opaque declarations are compiled in the
- Xoutput header file into character array declarations of \fIsize\fP bytes.
- X.LP
- XStrings are special and are declared as a vector declaration:
- X.LP
- X.RS
- X\fBstring\fP \fIobject-ident\fP \fB[\fP \fImax-size\fP \fB]\fP
- X.RE
- X.LP
- XIf \fImax-size\fP is unspecified, then there is essentially no limit to
- Xthe maximum length of the string. String declarations get compiled into
- Xthe following:
- X.LP
- X.RS
- Xchar *\fIobject-ident\fP
- X.RE
- X.RE
- X.RE
- X.SS "Type Definitions"
- XThe only way to generate an XDR routine is to define a type. For
- Xevery type \fIzetype\fP you define, there is a corresponding
- XXDR routine named \fIxdr_zetype\fP.
- X.LP
- XThere are six ways to define a type:
- X.LP
- X\fItype-definition:\fP
- X.RS
- X.nf
- X\fItypedef\fP
- X\fIenumeration-def\fP
- X\fIstructure-def\fP
- X\fIvariable-length-array-def\fP
- X\fIdiscriminated-union-def\fP
- X\fIprogram-def\fP
- X.fi
- X.RE
- X.LP
- XThe first three are very similar to their
- X.B C
- Xnamesakes.
- X.B C
- Xdoes not have a formal type mechanism to define variable-length arrays and
- XXDR unions are quite different from their
- X.B C
- Xcounterparts. Program definitions are not really type definitions,
- Xbut they are useful nonetheless.
- X.LP
- XYou may not nest XDR definitions. For example, the following will
- Xcause \fIrpcgen\fP to choke:
- X.RS
- X.nf
- Xstruct dontdoit {
- X struct ididit {
- X int oops;
- X } sorry;
- X enum ididitagain { OOPS, WHOOPS } iapologize;
- X};
- X.fi
- X.RE
- X.SS \fRTypedefs
- XAn XDR \fBtypedef\fP looks as follows:
- X.LP
- X\fItypedef:\fP
- X.RS
- X\fBtypedef\fP \fIdeclaration\fP \fB;\fP
- X.RE
- XThe \fIobject-ident\fP part of \fIdeclaration\fP is the name of the new type,
- Xwhereas the \fItype-name\fP part is the name of the type from which it is
- Xderived.
- X.LP
- X.SS "\fIEnumeration Types"
- XThe syntax is:
- X.LP
- X\fIenumeration-def:\fP
- X.RS
- X\fBenum\fP \fIenum-ident\fP \fB{\fP
- X.RS
- X\fIenum-list\fP
- X.RE
- X\fB};\fP
- X.RE
- X.LP
- X\fIenum-list:\fP
- X.RS
- X\fIenum-symbol-ident\fP [ \fB=\fP \fIassignment\fP ]
- X.br
- X\fIenum-symbol-ident\fP [ \fB=\fP \fIassignment\fP ] \fB,\fP \fIenum-list\fP
- X.RE
- X.LP
- X(\fIassignment\fP may be either an integer or a symbolic constant)
- X.LP
- XIf there is no explicit assignment, then the implicit assignment is the
- Xvalue of the previous enumeration plus 1. If not explicitly assigned,
- Xthe first enumeration receives the value 0.
- X.SS \fIStructures
- X\fIstructure-def:\fP
- X.RS
- X\fBstruct\fP \fIstruct-ident\fP \fB{\fP
- X.RS
- X\fIdeclaration-list\fP
- X.RE
- X\fB};\fP
- X.RE
- X.LP
- X\fIdeclaration-list:\fP
- X.RS
- X\fIdeclaration\fP \fB;\fP
- X.br
- X\fIdeclaration\fP \fB;\fP \fIdeclaration-list\fP
- X.RE
- X.RE
- X.LP
- X.SS "\fIVariable-Length Arrays"
- X\fIvariable-length-array-def:\fP
- X.RS
- X\fBarray\fP \fIarray-ident\fP \fB{\fP
- X.RS
- X\fBunsigned\fP \fIlength-identifer\fP \fB;\fP
- X.br
- X\fIvector-declaration\fP \fB;\fP
- X.RE
- X\fB};\fP
- X.RE
- X.LP
- XA variable length array definition looks much like a structure
- Xdefinition. Here's an example:
- X.RS
- X.nf
- Xarray mp_int {
- X unsigned len;
- X short val[MAX_MP_LENGTH];
- X};
- X.fi
- X.RE
- XThis is compiled into:
- X.RS
- X.nf
- Xstruct mp_int {
- X unsigned len;
- X short *val;
- X};
- Xtypedef struct mp_int mp_int;
- X.fi
- X.RE
- X.SS "\fIDisriminated Unions"
- X\fIdiscriminated-union-def:\fP
- X.RS
- X\fBunion\fP \fIunion-ident\fP \fBswitch\fP \fB(\fP \fIdiscriminant-declaration\fP \fB)\fP \fB{\fP
- X.RS
- X\fIcase-list\fP
- X.br
- X[ \fBdefault\fP \fB:\fP \fIdeclaration\fP \fB;\fP ]
- X.RE
- X\fB};\fP
- X.RE
- X.LP
- X\fIcase-list:\fP
- X.RS
- X\fBcase\fP \fIcase-ident\fP \fB:\fP \fIdeclaration\fP \fB;\fP
- X.br
- X\fBcase\fP \fIcase-ident\fP \fB:\fP \fIdeclaration\fP \fB;\fP \fIcase-list\fP
- X.RE
- X.LP
- X\fIdiscriminant-declaration:\fP
- X.RS
- X\fIdeclaration\fP
- X.RE
- X.LP
- XThe union definition looks like a cross between a C-union and a C-switch.
- XAn example:
- X.RS
- X.nf
- Xunion net_object switch (net_kind kind) {
- Xcase MACHINE:
- X struct sockaddr_in sin;
- Xcase USER:
- X int uid;
- Xdefault:
- X string whatisit;
- X};
- X.fi
- X.RE
- XCompiles into:
- X.RS
- X.nf
- Xstruct net_object {
- X net_kind kind;
- X union {
- X struct sockaddr_in sin;
- X int uid;
- X char *whatisit;
- X } net_object;
- X};
- Xtypedef struct net_object net_object;
- X.fi
- X.RE
- XNote that the name of the union component of the output struct is the
- Xsame as the name of the type itself.
- X.SS "\fIProgram Definitions"
- X\fIprogram-def:\fP
- X.RS
- X\fBprogram\fP \fIprogram-ident\fP \fB{\fP
- X.RS
- X\fIversion-list\fP
- X.RE
- X\fB}\fP \fB=\fP \fIprogram-number\fP \fB;\fP
- X.RE
- X.LP
- X\fIversion-list:\fP
- X.RS
- X\fIversion\fP
- X.br
- X\fIversion\fP \fIversion-list\fP
- X.RE
- X\fIversion:\fP
- X.RS
- X\fBversion\fP \fIversion-ident\fP \fB{\fP
- X.RS
- X\fIprocedure-list\fP
- X.RE
- X\fB} =\fP \fIversion-number\fP \fB;\fP
- X.RE
- X\fIprocedure-list:\fP
- X.RS
- X\fIprocedure-declaration\fP
- X.br
- X\fIprocedure-declaration procedure-list\fP
- X.RE
- X\fIprocedure-declaration:\fP
- X.RS
- X\fItype-name\fP \fIprocedure-ident\fP \fB(\fP \fItype-name\fP \fB)\fP \fB=\fP \fIprocedure-number\fP \fB;\fP
- X.RE
- X.LP
- XProgram definitions look like nothing you've ever seen before, so we
- Xturn to an example to explain them. Suppose you wanted to create server
- Xthat could get or set the date. It's declaration might look like this:
- X.RS
- X.nf
- Xprogram DATE_PROG {
- X version DATE_VERS {
- X date DATE_GET(timezone) = 1;
- X void DATE_SET(date) = 2; /* Greenwich mean time */
- X } = 1;
- X} = 100;
- X.fi
- X.RE
- XIn the header file, this compiles into the following:
- X.RS
- X.nf
- X#define DATE_PROG 100
- X#define DATE_VERS 1
- X#define DATE_GET 1
- X#define DATE_SET 2
- X.fi
- X.RE
- XThese \fBdefine\fP's are intended for use by the client program to
- Xreference the remote procedures.
- X.LP
- XIf you are using \fIrpcgen\fP to compile your server, then there are
- Xsome important things for you to know. The server interfaces to
- Xyour local procedures by expecting a
- X.B C
- Xfunction with the same name as that in the program definition, but in all
- Xlower-case letters and followed by the version number. Here is the local
- Xprocedure that implements DATE_GET:
- X.RS
- X.nf
- Xdate * /* always returns a pointer to the results */
- Xdate_get_1(tz)
- X timezone *tz; /* always takes a a pointer to the arguments */
- X{
- X static date d; /* must be static! */
- X
- X /*
- X * figure out the date
- X * and store it in d
- X */
- X return(&d);
- X}
- X.fi
- X.RE
- XThe name of the routine is the same as the \fB#define\fP'd name, but in all
- Xlower case letters and followed by the version number. XDR will recursively
- Xfree the argument after getting the
- Xresults from your local procedure, so you should copy from the argument
- Xany data that you will need between calls. However, XDR neither allocates
- Xnor frees your results. You must take care of their storage yourself.
- X.LP
- X.SS "Make Inference Rules For Compiling XDR Headers"
- X.LP
- XIt is possible to set up suffix transformation rules in
- X.IR make (1)
- Xfor compiling XDR routines and header files. The
- Xconvention is that RPCL protocol files have the extension
- X.BR .x .
- XThe \fImake\fP rules to do this are:
- X.nf
- X .SUFFIXES: .x
- X .x.c:
- X rpcgen -c $< -o $@
- X
- X .x.h:
- X rpcgen -h $< -o $@
- X.fi
- X.SH "SEE ALSO"
- X\fIRemote Procedure Call: Programming Guide\fP
- Xand \fIExternal Data Representation: Protocol Specification\fP
- Xin\fI Networking on the Sun Workstation\fP
- X.SH BUGS
- XName clashes can occur when using program definitions, since the apparent
- Xscoping does not really apply. Most of these can be avoided by giving
- Xunique names for programs, versions, procedures and types.
- SHAR_EOF
- if test 11239 -ne "`wc -c < 'rpc/rpcgen/rpcgen.1'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/rpcgen.1'" '(should have been 11239 characters)'
- fi
- chmod 444 'rpc/rpcgen/rpcgen.1'
- fi
- echo shar: "extracting 'rpc/rpcgen/xdr_update.c'" '(1993 characters)'
- if test -f 'rpc/rpcgen/xdr_update.c'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/xdr_update.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/xdr_update.c'
- X/*
- X * xdr_update.c: Additions to release 3.0 XDR routines required
- X * for rpcgen. These routines are from release 3.2BETA and
- X * may be updated before final release.
- X *
- X * Copyright (C) 1986, Sun Microsystems, Inc.
- X *
- X */
- X
- X#include <rpc/rpc.h>
- X#define NULL 0
- X#define LASTUNSIGNED ((u_int)0-1)
- X
- X/*
- X * xdr_pointer():
- X *
- X * XDR a pointer to a possibly recursive data structure. This
- X * differs with xdr_reference in that it can serialize/deserialiaze
- X * trees correctly.
- X *
- X * What's sent is actually a union:
- X *
- X * union object_pointer switch (boolean b) {
- X * case TRUE: object_data data;
- X * case FALSE: void nothing;
- X * }
- X *
- X * > objpp: Pointer to the pointer to the object.
- X * > obj_size: size of the object.
- X * > xdr_obj: routine to XDR an object.
- X *
- X */
- Xbool_t
- Xxdr_pointer(xdrs,objpp,obj_size,xdr_obj)
- X register XDR *xdrs;
- X char **objpp;
- X u_int obj_size;
- X xdrproc_t xdr_obj;
- X{
- X
- X bool_t more_data;
- X
- X more_data = (*objpp != NULL);
- X if (! xdr_bool(xdrs,&more_data)) {
- X return(FALSE);
- X }
- X if (! more_data) {
- X *objpp = NULL;
- X return(TRUE);
- X }
- X return(xdr_reference(xdrs,objpp,obj_size,xdr_obj));
- X}
- X
- X/*
- X * xdr_vector():
- X *
- X * XDR a fixed length array. Unlike variable-length arrays,
- X * the storage of fixed length arrays is static and unfreeable.
- X * > basep: base of the array
- X * > size: size of the array
- X * > elemsize: size of each element
- X * > xdr_elem: routine to XDR each element
- X */
- Xbool_t
- Xxdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
- X register XDR *xdrs;
- X register char *basep;
- X register u_int nelem;
- X register u_int elemsize;
- X register xdrproc_t xdr_elem;
- X{
- X register u_int i;
- X register char *elptr;
- X
- X elptr = basep;
- X for (i = 0; i < nelem; i++) {
- X if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
- X return(FALSE);
- X }
- X elptr += elemsize;
- X }
- X return(TRUE);
- X}
- SHAR_EOF
- if test 1993 -ne "`wc -c < 'rpc/rpcgen/xdr_update.c'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/xdr_update.c'" '(should have been 1993 characters)'
- fi
- chmod 664 'rpc/rpcgen/xdr_update.c'
- fi
- echo shar: "extracting 'rpc/rpcgen/test/Makefile'" '(1274 characters)'
- if test -f 'rpc/rpcgen/test/Makefile'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/test/Makefile'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/Makefile'
- X# Makefile for the demo rpc service for rpcgen
- X#
- X# There are three source files used by this makefile:
- X# demo_xdr.x Demo protocol specification used as input
- X# by rpcgen to generate demo_xdr.h (xdr
- X# defines and data type decarations),
- X# demo_xdr.c (xdr data type routines),
- X# and demo.c (server program shell)
- X# demo_proc.c The actual procedure handlers for the server.
- X# demo_clnt.c The client program.
- X
- X.SUFFIXES: .x .c .h .o
- XCC = cc
- X
- X# REL3_0 should be defined in CFLAGS if using a pre-3.2 rpc library
- XCFLAGS = -DREL3_0
- X
- XRPCGEN = ../rpcgen
- XPROTO = udp
- X
- XSOBJS = demo.o demo_proc.o demo_xdr.o
- XCOBJS = demo_clnt.o demo_xdr.o
- X
- X# RPCLIB should be the rpc library, or commented out if included in libc.
- X# xdr_update.o should be included if linking with a pre-3.2 rpc library.
- X#RPCLIB = -lrpc
- XRPCLIB = ../xdr_update.o
- X
- X.x.c:
- X $(RPCGEN) -c $< -o $@
- X.x.h:
- X $(RPCGEN) -h $< -o $@
- X
- Xall: demo_svr demo_clnt
- X
- Xdemo_svr: $(SOBJS)
- X $(CC) $(CFLAGS) -o $@ $(SOBJS) $(RPCLIB)
- X
- Xdemo_clnt: $(COBJS)
- X $(CC) $(CFLAGS) -o $@ $(COBJS) $(RPCLIB)
- X
- Xdemo.c: demo_xdr.x demo_xdr.h
- X $(RPCGEN) -s $(PROTO) demo_xdr.x -o $@
- X
- Xdemo_xdr.c: demo_xdr.x
- Xdemo_xdr.o: demo_xdr.c demo_xdr.h
- Xdemo_proc.o: demo_xdr.h
- Xdemo_clnt.o: demo_xdr.h
- X
- Xclean:
- X -rm -f *.o *.h demo_clnt demo_svr demo_xdr.c demo.c
- SHAR_EOF
- if test 1274 -ne "`wc -c < 'rpc/rpcgen/test/Makefile'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/test/Makefile'" '(should have been 1274 characters)'
- fi
- chmod 664 'rpc/rpcgen/test/Makefile'
- fi
- echo shar: "extracting 'rpc/rpcgen/test/demo_clnt.c'" '(3254 characters)'
- if test -f 'rpc/rpcgen/test/demo_clnt.c'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_clnt.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_clnt.c'
- X/*
- X * Client program for rpcgen demo
- X */
- X
- X#include <stdio.h>
- X#include <rpc/rpc.h>
- X#include "demo_xdr.h"
- X
- Xchar *Prog, *Host;
- X
- Xstruct Calls {
- X char *name; /* name of call */
- X enum ret_status arg_type; /* arg type expected */
- X int procno; /* proc number */
- X} Calls[] = {
- X { "ctime", RET_CLOCK, CTIME },
- X { "localtime", RET_CLOCK, LOCALTIME },
- X { "gmtime", RET_CLOCK, GMTIME },
- X { "asctime", RET_TM, ASCTIME },
- X { "timezone", RET_TZ, TIMEZONE },
- X { "dysize", RET_YEAR, DYSIZE },
- X { NULL }
- X};
- X
- Xchar *Arg;
- Xdemo_res Res;
- Xxdrproc_t Xargs, Xres;
- X
- Xmain(argc, argv)
- Xchar **argv;
- X{
- X struct Calls *callp;
- X int ret;
- X
- X Prog = argv[0];
- X if (argc < 3)
- X usage();
- X
- X for (callp = Calls; callp->name; callp++)
- X if (!strcmp(callp->name, argv[2]))
- X break;
- X if (callp->name == NULL) {
- X fprintf(stderr, "%s: call \"%s\" not recognized.\n",
- X Prog, argv[2]);
- X exit(1);
- X }
- X Host = argv[1];
- X argc -= 3; argv += 3;
- X getargs(argc, argv, callp);
- X Xres = xdr_demo_res;
- X if (ret = callrpc(Host, DEMOPROG, DEMOVERS, callp->procno,
- X Xargs, Arg, Xres, &Res))
- X {
- X fprintf(stderr, "%s: rpc failed: ", Prog);
- X clnt_perrno(ret);
- X fprintf(stderr, "\n");
- X exit(1);
- X }
- X printres(callp);
- X}
- X
- Xgetargs(argc, argv, callp)
- Xint argc;
- Xchar **argv;
- Xstruct Calls *callp;
- X{
- X static long l_arg;
- X static timeval tv;
- X static tzargs tz_arg;
- X
- X gettimeofday(&tv, &tz_arg);
- X switch (callp->arg_type) {
- X case RET_CLOCK:
- X l_arg = (long)(argc > 0? atoi(argv[0]) : tv.tv_sec);
- X Arg = (char *)&l_arg;
- X Xargs = xdr_clock;
- X break;
- X case RET_TM:
- X l_arg = (long)(argc > 0? atoi(argv[0]) : tv.tv_sec);
- X Arg = (char *)localtime(&l_arg);
- X Xargs = xdr_tm;
- X break;
- X case RET_TZ:
- X if (argc == 1) {
- X fprintf(stderr, "\
- X%s: call \"%s\" takes two arguments.\n", Prog, callp->name);
- X exit(1);
- X } else if (argc > 1) {
- X tz_arg.zone = atoi(argv[0]);
- X tz_arg.dst = atoi(argv[1]);
- X }
- X Arg = (char *)&tz_arg;
- X Xargs = xdr_tzargs;
- X break;
- X case RET_YEAR:
- X l_arg = (argc > 0? atoi(argv[0]) : 1986);
- X Arg = (char *)&l_arg;
- X Xargs = xdr_int;
- X break;
- X default:
- X fprintf(stderr, "%s: panic: unknown arg type %d\n",
- X Prog, callp->arg_type);
- X exit(1);
- X }
- X}
- X
- Xprintres(callp)
- Xstruct Calls *callp;
- X{
- X switch (Res.which) {
- X case RET_DATE:
- X printf("date from %s: %s\n", Host, Res.demo_res.date);
- X break;
- X case RET_TM:
- X#define TZP(x) Res.demo_res.tmp->tm_/**/x
- X printf("\
- Xtime info from %s: sec=%d, min=%d, hour=%d, mday=%d, mon=%d,\n\
- X year=%d, wday=%d, yday=%d, isdst=%d\n",
- X Host, TZP(sec), TZP(min), TZP(hour), TZP(mday),
- X TZP(mon), TZP(year), TZP(wday), TZP(yday), TZP(isdst));
- X break;
- X case RET_STR:
- X printf("Return string from %s: %s\n", Host, Res.demo_res.str);
- X break;
- X case RET_DAYS:
- X printf("Return from %s: %d days\n", Host, Res.demo_res.days);
- X break;
- X case RET_ERROR:
- X printf("%s returned error %d (%s)\n", Host,
- X Res.demo_res.err.err_number,
- X Res.demo_res.err.err_text);
- X break;
- X default:
- X printf("%s returned an unknown return type (%d)\n",
- X Host, Res.which);
- X break;
- X }
- X}
- X
- Xusage()
- X{
- X struct Calls *callp;
- X
- X fprintf(stderr, "usage: %s host call [args]\n", Prog);
- X fprintf(stderr, "valid calls are:\n");
- X for (callp = Calls; callp->name; callp++)
- X fprintf(stderr, "\t%s\n", callp->name);
- X exit(1);
- X}
- SHAR_EOF
- if test 3254 -ne "`wc -c < 'rpc/rpcgen/test/demo_clnt.c'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/test/demo_clnt.c'" '(should have been 3254 characters)'
- fi
- chmod 664 'rpc/rpcgen/test/demo_clnt.c'
- fi
- echo shar: "extracting 'rpc/rpcgen/test/demo_proc.c'" '(833 characters)'
- if test -f 'rpc/rpcgen/test/demo_proc.c'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_proc.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_proc.c'
- X/*
- X * Demo procedures
- X */
- X
- X#include <stdio.h>
- X#include <rpc/rpc.h>
- X#include "demo_xdr.h"
- Xstatic demo_res res;
- X
- Xdemo_res *
- Xctime_5(arg)
- Xclock *arg;
- X{
- X res.which = RET_DATE;
- X res.demo_res.date = (date)ctime(arg);
- X return &res;
- X}
- X
- Xdemo_res *
- Xlocaltime_5(arg)
- Xclock *arg;
- X{
- X res.which = RET_TM;
- X res.demo_res.tmp = (tm *)localtime(arg);
- X return &res;
- X}
- X
- Xdemo_res *
- Xgmtime_5(arg)
- Xclock *arg;
- X{
- X res.which = RET_TM;
- X res.demo_res.tmp = (tm *)gmtime(arg);
- X return &res;
- X}
- X
- Xdemo_res *
- Xasctime_5(arg)
- Xtm *arg;
- X{
- X res.which = RET_DATE;
- X res.demo_res.date = (date)asctime(arg);
- X return &res;
- X}
- X
- Xdemo_res *
- Xtimezone_5(arg)
- Xtzargs *arg;
- X{
- X res.which = RET_STR;
- X res.demo_res.str = (str)timezone(arg->zone, arg->dst);
- X return &res;
- X}
- X
- Xdemo_res *
- Xdysize_5(val)
- Xint *val;
- X{
- X res.which = RET_DAYS;
- X res.demo_res.days = dysize(*val);
- X return &res;
- X}
- SHAR_EOF
- if test 833 -ne "`wc -c < 'rpc/rpcgen/test/demo_proc.c'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/test/demo_proc.c'" '(should have been 833 characters)'
- fi
- chmod 664 'rpc/rpcgen/test/demo_proc.c'
- fi
- echo shar: "extracting 'rpc/rpcgen/test/demo_xdr.x'" '(1834 characters)'
- if test -f 'rpc/rpcgen/test/demo_xdr.x'
- then
- echo shar: "will not over-write existing file 'rpc/rpcgen/test/demo_xdr.x'"
- else
- sed 's/^X//' << \SHAR_EOF > 'rpc/rpcgen/test/demo_xdr.x'
- X/*
- X * This file defines the protocol to support a demo rpc
- X * service and is designed to be processed by the `rpcgen'
- X * protocol compiler. The Sun ctime(3) routines are used
- X * as examples. See the rpcgen manual page for more detailed
- X * information.
- X */
- X
- X#ifdef REL3_0
- X#ifndef NULL
- X# define NULL 0
- X#endif
- X#endif
- X
- X
- X/*
- X * argument / result data types
- X */
- X
- X#define DATELEN 26
- Xtypedef string date[DATELEN];
- X
- X#define STRLEN 80
- Xtypedef string str[STRLEN];
- X
- Xtypedef long clock;
- X
- Xstruct tm {
- X int tm_sec;
- X int tm_min;
- X int tm_hour;
- X int tm_mday;
- X int tm_mon;
- X int tm_year;
- X int tm_wday;
- X int tm_yday;
- X int tm_isdst;
- X};
- X
- Xstruct timeval {
- X u_long tv_sec;
- X long tv_usec;
- X};
- X
- Xstruct timez {
- X int tz_minuteswest;
- X int tz_dsttime;
- X};
- X
- Xstruct tzargs {
- X int zone;
- X int dst;
- X};
- X
- X
- X/*
- X * There is one generic data type for the result. This is implemented
- X * as a union switch. The specific union element returned is specified
- X * by ret_status.
- X */
- X
- Xenum ret_status {
- X RET_DATE, RET_TM, RET_STR, RET_DAYS, RET_CLOCK, RET_TZ, RET_YEAR,
- X RET_ERROR
- X};
- X
- Xstruct ret_err {
- X int err_number;
- X str err_text;
- X};
- X
- Xunion demo_res switch (ret_status which) {
- X case RET_DATE:
- X date date;
- X case RET_TM:
- X tm *tmp;
- X case RET_STR:
- X str str;
- X case RET_DAYS:
- X int days;
- X case RET_ERROR:
- X ret_err err;
- X};
- X
- X
- X/*
- X * This section declares the individual procedures which are supported
- X * by this protocol. The program number and version numbers are
- X * arbitrary in this case. Procedures correspond to the ctime(3)
- X * time routines.
- X */
- X
- Xprogram DEMOPROG {
- X version DEMOVERS {
- X demo_res /* date */ CTIME(clock) = 1;
- X demo_res /* tm */ LOCALTIME(clock) = 2;
- X demo_res /* tm */ GMTIME(clock) = 3;
- X demo_res /* date */ ASCTIME(tm) = 4;
- X demo_res /* str */ TIMEZONE(tzargs) = 5;
- X demo_res /* days */ DYSIZE(int) = 6;
- X } = 5;
- X} = 123456;
- SHAR_EOF
- if test 1834 -ne "`wc -c < 'rpc/rpcgen/test/demo_xdr.x'`"
- then
- echo shar: "error transmitting 'rpc/rpcgen/test/demo_xdr.x'" '(should have been 1834 characters)'
- fi
- chmod 664 'rpc/rpcgen/test/demo_xdr.x'
- fi
- exit 0
- # End of shell archive
-
-